#include "stdafx.h"
#include "System1Machine.h"

void CNamcoSystem1MMU::MapBank(int bank,u32 data)
{
if(data >= 0x200)			//map in rom
	{
	message("%s: mapping rom to $%04X, bank $%03X\n",Name,bank*0x2000,data & 0x1FF);
	BankType[bank] = BANK_READ;
	BankPtr[bank] = Owner->ROM + ((data & 0x1FF) * 0x2000);
	return;
	}
switch(data)				//else map in something else
	{
	case 0x170:				//map in palette banks
	case 0x171:
	case 0x172:
	case 0x173:
		//message("%s: mapping palette ram to $%04X\n",Name,bank*0x2000);
		BankType[bank] = BANK_READFUNC | BANK_WRITEFUNC;
		BankRead[bank] = BankReadPaletteRAM;
		BankWrite[bank] = BankWritePaletteRAM;
		return;
	case 0x178:				//map in video ram banks
	case 0x179:
	case 0x17A:
	case 0x17B:
		//message("%s: mapping video ram to $%04X, bank %d\n",Name,bank*0x2000,data & 3);
		BankType[bank] = BANK_READ | BANK_WRITE;
		BankPtr[bank] = Owner->VideoRAM + ((data & 3) * 0x2000);
		return;
	case 0x17C:				//key chip bank
		message("%s: mapping key chip to $%04X\n",Name,bank*0x2000);
		BankType[bank] = BANK_READFUNC | BANK_WRITEFUNC;
		BankRead[bank] = BankReadKeyChip;
		BankWrite[bank] = BankWriteKeyChip;
	case 0x17E:				//map in sprite ram
		//message("%s: mapping sprite ram to $%04X\n",Name,bank*0x2000);
		BankType[bank] = BANK_READFUNC | BANK_WRITEFUNC;
		BankRead[bank] = BankReadSpriteRAM;
		BankWrite[bank] = BankWriteSpriteRAM;
		return;
	case 0x17F:				//map in sound ram
		//message("%s: mapping sound ram to $%04X\n",Name,bank*0x2000);
		BankType[bank] = BANK_READFUNC | BANK_WRITEFUNC;
		BankRead[bank] = BankReadSoundRAM;
		BankWrite[bank] = BankWriteSoundRAM;
		return;
	case 0x180:				//map in ram banks
	case 0x181:
	case 0x182:
	case 0x183:
		//message("%s: mapping in ram to $%04X, bank %d\n",Name,bank*0x2000,data & 3);
		BankType[bank] = BANK_READ | BANK_WRITE;
		BankPtr[bank] = RAMPtr + ((data & 3) * 0x2000);
		return;
	}
//message("%s: bad bankswitch data value $%03X, bank = %d ($%04X)\n",Name,data,bank,bank*0x2000);
}

u8 CNamcoSystem1MMU::BankReadSpriteRAM(void *user,u32 addr)
{
CSystem1Machine *M = (CSystem1Machine*)user;

if(addr < 0x1000)
	return(M->SpriteRAM[addr & 0xFFF]);
return(M->PControl[addr & 0x1F]);
}

void CNamcoSystem1MMU::BankWriteSpriteRAM(void *user,u32 addr,u8 data)
{
CSystem1Machine *M = (CSystem1Machine*)user;

if(addr < 0x1000)
	M->SpriteRAM[addr & 0xFFF] = data;
else
	M->PControl[addr & 0x1F] = data;
}

u8 CNamcoSystem1MMU::BankReadSoundRAM(void *user,u32 addr)
{
CSystem1Machine *M = (CSystem1Machine*)user;

addr &= 0x1FFF;
if((addr & 0x1000) == 0x1000)
	{
	return(M->SharedRAM[addr & 0x7FF]);
	}
else
	return(M->SoundRAM[addr & 0x3FF]);
message("reading sound ram addr $%04X\n",addr);
return(0);
}

void CNamcoSystem1MMU::BankWriteSoundRAM(void *user,u32 addr,u8 data)
{
CSystem1Machine *M = (CSystem1Machine*)user;

if((addr & 0x1000) == 0x1000)
	{
	if(addr == 0x1000)
		{
		M->MCUPatchWrite(data);
		return;
		}
	M->SharedRAM[addr & 0x7FF] = data;
	return;
	}
else
	{
	M->SoundRAM[addr & 0x3FF] = data;
	return;
	}
message("writing sound ram addr $%04X = $%02X\n",addr,data);
}

u8 CNamcoSystem1MMU::BankReadPaletteRAM(void *user,u32 addr)
{
CSystem1Machine *M = (CSystem1Machine*)user;

//message("reading palette ram addr $%04X\n",addr);
return(M->PaletteRAM[addr & 0x7FFF]);
}

void CNamcoSystem1MMU::BankWritePaletteRAM(void *user,u32 addr,u8 data)
{
CSystem1Machine *M = (CSystem1Machine*)user;

//message("writing palette ram addr $%04X = $%02X\n",addr,data);
M->WritePalette(addr & 0x7FFF,data);
}

u8 CNamcoSystem1MMU::BankReadKeyChip(void *user,u32 addr)
{
CSystem1Machine *M = (CSystem1Machine*)user;
u8 ret = 0;

message("reading key chip, $%04X = $%02X\n",addr,ret);
return(ret);
}

void CNamcoSystem1MMU::BankWriteKeyChip(void *user,u32 addr,u8 data)
{
CSystem1Machine *M = (CSystem1Machine*)user;

message("writing key chip, $%04X = $%02X\n",addr,data);
}

static u8 MAMEROM[0x2000];		//mame has good ideas

CNamcoSystem1MMU::CNamcoSystem1MMU(CSystem1Machine *O, u8 *R,char *n)
{
int i;

/* create mamerom */
for(i=0;i<0x2000;i+=2)
	*((u16*)(MAMEROM + i)) = 0x20FE;
*((u16*)(MAMEROM + 0x1FF8)) = 0xFF00;
/* done */
Owner = O;
RAMPtr = R;
strncpy(Name,n,32);
}

CNamcoSystem1MMU::~CNamcoSystem1MMU()
{
}

void CNamcoSystem1MMU::Reset()
{
int i;

for(i=0;i<8;i++)
	{
	BankReg[i] = 0;
	BankPtr[i] = 0;
	BankType[i] = 0;
	}
}

u8 CNamcoSystem1MMU::Read(void *user,u32 addr)
{
int b,t;

b = addr >> 13;
t = BankType[b];
if(t & BANK_READFUNC)
	return(BankRead[b](user,addr));
if(t & BANK_READ)
	return(BankPtr[b][addr & 0x1FFF]);
//message("%smmu: reading unmapped main cpu space, $%04X\n",Name,addr);
return(MAMEROM[addr & 0x1FFF]);
}

void CNamcoSystem1MMU::Write(void *user,u32 addr,u8 data)
{
int b,t;

b = addr >> 13;
t = BankType[b];
if(t & BANK_WRITEFUNC)
	BankWrite[b](user,addr,data);
else if(t & BANK_WRITE)
	BankPtr[b][addr & 0x1FFF] = data;
else
	message("%smmu: writing unmapped main cpu space, $%04X = $%02X\n",Name,addr,data);
}

void CNamcoSystem1MMU::Bankswitch(u32 addr,u8 data)
{
int Bank = (addr >> 9) & 7;

if(addr & 1)			//write lower byte
	{
	BankReg[Bank] &= 0x300;
	BankReg[Bank] |= data;
	}
else						//write upper two bits
	{
	BankReg[Bank] &= 0xFF;
	BankReg[Bank] |= (data & 3) << 8;
	}
MapBank(Bank,BankReg[Bank]);
}
